package com.fjsh.config;

import feign.*;
import feign.codec.Decoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * 注意： 若RequestContextHolder.getRequestAttributes()获取到是空值
 * 解决方法一：若有以上依赖，则检查熔断是否开启，开启后若想直接使用则可以把熔断策略改为SEMAPHORE,官方建议为并发策略THREAD
 * 使用并发策略需要重写 HystrixConcurrencyStrategy 类，并重写 wrapCallable 方法
 * 解决方法二：通过aop的方式使用ThreadLocal提前存储所需的值，然后在当前拦截器中去获取
 * 以上解决方法待测
 *
 * 此拦截器可根据自身需求做对应处理，如白名单功能等
 */
@Configuration
public class FeignConfig implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {

        // 将认证信息带到服务端
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (!StringUtils.isEmpty(attributes)){
            HttpServletRequest request = attributes.getRequest();
            requestTemplate.header(HttpHeaders.AUTHORIZATION, request.getHeader(HttpHeaders.AUTHORIZATION));
        }
    }
    // 以下配置http解码，未配置有可能会报异常
    @Bean
    public Decoder feignDecoder() {

        return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
    }
    public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new GateWayMappingJackson2HttpMessageConverter());
        return () -> httpMessageConverters;
    }
    public class GateWayMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {

        GateWayMappingJackson2HttpMessageConverter(){
            List<MediaType> mediaTypes = new ArrayList<>();
            mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8"));
            setSupportedMediaTypes(mediaTypes);
        }
    }

}